package com.overlord.im.client.start;

import com.overlord.im.client.api.ClientMsgListener;
import com.overlord.im.client.api.MessageApi;
import com.overlord.im.client.netty.channel.ImClientChannelInitializer;
import com.overlord.im.client.netty.handler.ImClientHandler;
import com.overlord.im.commons.exception.ImException;
import com.overlord.im.commons.message.Protocol;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @ClassName ImClient
 * @Author wuwei
 * @Description NONE
 * @Date 2020/5/29 17:11
 **/
public class ImClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(ImClient.class);

    private EventLoopGroup group = new NioEventLoopGroup();

    private int port;

    private String host;

    private Protocol protocol;

    private ClientMsgListener clientMsgListener;

    private ImClientHandler imClientHandler;

    public ImClient(int port, String host, Protocol protocol, ClientMsgListener clientMsgListener) {
        this.port = port;
        this.host = host;
        this.protocol = protocol;
        this.clientMsgListener = clientMsgListener;
    }

    public void start() {
        imClientHandler = new ImClientHandler(clientMsgListener);
        ImClientChannelInitializer imClientChannelInitializer =
                new ImClientChannelInitializer(protocol, imClientHandler);
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group).channel(NioSocketChannel.class).remoteAddress(host, port)
                .option(ChannelOption.SO_KEEPALIVE, true).option(ChannelOption.TCP_NODELAY, true)
                .handler(imClientChannelInitializer);
        ChannelFuture future = bootstrap.connect();
        //客户端断线重连逻辑
        future.addListener((ChannelFutureListener) future1 -> {
            if (future1.isSuccess()) {
                LOGGER.info("连接Netty服务端成功");
            } else {
                LOGGER.info("连接失败，进行断线重连");
                future1.channel().eventLoop().schedule(() -> start(), 20, TimeUnit.SECONDS);
            }
        });
        try {
            future.get(10, TimeUnit.SECONDS);
        } catch (InterruptedException | TimeoutException | ExecutionException e) {
            throw new ImException("[client] connect to connector failed!");
        }
    }

    public MessageApi messageApi() {
        return new MessageApi(imClientHandler);
    }
}
